﻿using FRRJIf;
using RJi.FanucInterface3.Common.Enum;

namespace RJi.FanucInterface3.Common.Internal;

internal class DataTableWrapper(DataTable coreTable, Dictionary<string, VariableMetadata> variableMetadataCache) : IDataTableWrapper
{
    public IDataTableWrapper RegisterAlarmHistory(int count, string key = "ALARM_LIST")
    {
        count = Math.Clamp(count, 1, 100);
        var alarm = coreTable.AddAlarm(FRIF_DATA_TYPE.ALARM_LIST, count);
        variableMetadataCache[key] = new VariableMetadata(alarm, typeof(DataAlarm), true, 1, count);
        return this;
    }

    public IDataTableWrapper RegisterCurPos(int group = 1, string key = "CUR_POS")
    {
        var curPos = coreTable.AddCurPos(FRIF_DATA_TYPE.CURPOS, group);
        variableMetadataCache[key] = new VariableMetadata(curPos, typeof(DataCurPos));
        return this;
    }

    public IDataTableWrapper RegisterCurPosWithUserFrame(int userFrame = 1, int group = 1, string key = "CUR_POS_USER_FRAME")
    {
        var curPosWithUserFrame = coreTable.AddCurPosUF(FRIF_DATA_TYPE.CURPOS, group, userFrame);
        variableMetadataCache[key] = new VariableMetadata(curPosWithUserFrame, typeof(DataCurPos));
        return this;
    }

    public IDataTableWrapper RegisterNumReg(int startIndex, int endIndex, string key = "NUM_REG")
    {
        startIndex = Math.Clamp(startIndex, 1, 200);
        endIndex = Math.Clamp(endIndex, 1, 200);
        if (startIndex > endIndex) endIndex = startIndex;
        var count = endIndex - startIndex + 1;
        var numReg = coreTable.AddNumReg(FRIF_DATA_TYPE.NUMREG_REAL, startIndex, endIndex);
        variableMetadataCache[key] = new VariableMetadata(numReg, typeof(DataNumReg), true, startIndex, count);
        return this;
    }

    public IDataTableWrapper RegisterPosReg(int startIndex, int endIndex, int group = 1, string key = "POS_REG")
    {
        startIndex = Math.Clamp(startIndex, 1, 100);
        endIndex = Math.Clamp(endIndex, 1, 100);
        if (startIndex > endIndex) endIndex = startIndex;
        var count = endIndex - startIndex + 1;
        var posReg = coreTable.AddPosReg(FRIF_DATA_TYPE.POSREG, group, startIndex, endIndex);
        variableMetadataCache[key] = new VariableMetadata(posReg, typeof(DataPosReg), true, startIndex, count);
        return this;
    }

    public IDataTableWrapper RegisterRegComment(int startIndex, int endIndex, RegCommentType commentType, string? key = null)
    {
        var maxLimit = commentType switch
        {
            RegCommentType.StrReg => 25, // 字符串类型最多25个
            RegCommentType.NumReg => 200, // 数值类型最多200个
            RegCommentType.PosReg => 100, // 位置类型最多100个
            _ => throw new ArgumentException("不支持的注释类型")
        };

        startIndex = Math.Clamp(startIndex, 1, maxLimit);
        endIndex = Math.Clamp(endIndex, 1, maxLimit);
        if (startIndex > endIndex) endIndex = startIndex;
        var count = endIndex - startIndex + 1;

        key ??= $"{commentType.ToString().ToUpper()}_COMMENT";
        var regComment = coreTable.AddString((FRIF_DATA_TYPE)commentType, startIndex, endIndex);
        variableMetadataCache[key] = new VariableMetadata(regComment, typeof(DataString), true, startIndex, count, Ext: "REG_COMMENT");
        return this;
    }

    public IDataTableWrapper RegisterStringReg(int startIndex, int endIndex, string key = "STRING_REG")
    {
        startIndex = Math.Clamp(startIndex, 1, 25);
        endIndex = Math.Clamp(endIndex, 1, 25);
        if (startIndex > endIndex) endIndex = startIndex;
        var count = endIndex - startIndex + 1;
        var stringReg = coreTable.AddString(FRIF_DATA_TYPE.STRREG, startIndex, endIndex);
        variableMetadataCache[key] = new VariableMetadata(stringReg, typeof(DataString), true, startIndex, count, Ext: "STRING_REG");
        return this;
    }

    public IDataTableWrapper RegisterSysVar(string sysVarName, SysVarType varType = SysVarType.Real, string? key = null)
    {
        key ??= sysVarName;

        if (varType == SysVarType.Position)
        {
            var sysVarPos = coreTable.AddSysVarPos(FRIF_DATA_TYPE.SYSVAR_POS, sysVarName);
            variableMetadataCache[key] = new VariableMetadata(sysVarPos, typeof(DataSysVarPos), SysDataType: SysVarType.Position);
            return this;
        }

        var sysVar = coreTable.AddSysVar((FRIF_DATA_TYPE)varType, sysVarName);
        variableMetadataCache[key] = new VariableMetadata(sysVar, typeof(DataSysVar), SysDataType: varType);

        return this;
    }

    public IDataTableWrapper RegisterSysVars(string key, SysVarType varType = SysVarType.Real, params string[] sysVarNames)
    {
        if (varType == SysVarType.Position)
        {
            var sysVarPos = new DataSysVarPos[sysVarNames.Length];
            for (var i = 0; i < sysVarNames.Length; i++) sysVarPos[i] = coreTable.AddSysVarPos(FRIF_DATA_TYPE.SYSVAR_POS, sysVarNames[i]);
            variableMetadataCache[key] = new VariableMetadata(sysVarPos, typeof(DataSysVarPos[]), true, 1, sysVarNames.Length, SysVarType.Position);
            return this;
        }

        var sysVars = new DataSysVar[sysVarNames.Length];
        for (var i = 0; i < sysVarNames.Length; i++) sysVars[i] = coreTable.AddSysVar((FRIF_DATA_TYPE)varType, sysVarNames[i]);
        variableMetadataCache[key] = new VariableMetadata(sysVars, typeof(DataSysVar[]), true, 1, sysVarNames.Length, varType);
        return this;
    }

    public IDataTableWrapper RegisterTask(int index = 1, TaskVarType varType = TaskVarType.Task, string key = "TASK")
    {
        var task = coreTable.AddTask((FRIF_DATA_TYPE)varType, index);
        variableMetadataCache[key] = new VariableMetadata(task, typeof(DataTask));
        return this;
    }

    #region 暂时不用

    //写值用的，暂时不用
    public IDataTableWrapper RegisterPosRegCartesian(int startIndex, int endIndex, int group = 1, string key = "POS_REG_CARTESIAN")
    {
        startIndex = Math.Clamp(startIndex, 1, 100);
        endIndex = Math.Clamp(endIndex, 1, 100);
        if (startIndex > endIndex) endIndex = startIndex;
        var count = endIndex - startIndex + 1;
        var posRegCartesian = coreTable.AddPosRegXyzwpr(FRIF_DATA_TYPE.POSREG_XYZWPR, group, startIndex, endIndex);
        variableMetadataCache[key] = new VariableMetadata(posRegCartesian, typeof(DataPosRegXyzwpr));
        return this;
    }

    //写值用的，暂时不用
    public IDataTableWrapper RegisterPosRegMultipleGroup(int startIndex, int endIndex, string motionGroups = "C,J6", string key = "POS_REG_MG")
    {
        startIndex = Math.Clamp(startIndex, 1, 100);
        endIndex = Math.Clamp(endIndex, 1, 100);
        if (startIndex > endIndex) endIndex = startIndex;
        var count = endIndex - startIndex + 1;
        var posRegMultipleGroup = coreTable.AddPosRegMG(FRIF_DATA_TYPE.POSREGMG, motionGroups, startIndex, endIndex);
        variableMetadataCache[key] = new VariableMetadata(posRegMultipleGroup, typeof(DataPosRegMG));
        return this;
    }

    #endregion 暂时不用
}